var regionData = require("../../init/region.json");

module.exports = function(lab) {
    return {
        @initSession : function(session, name) {
            var session_provider = (@options("core") || {})[name];

            if (!session_provider) {
                throw @lab.errors.not_support;
            }

            if (session.currentOU) {
                return @.async.resolve(session.currentOU);
            } else {
                return lab.find("slime_system_settings",{
                    "key" : "id"
                }).then(function(result) {
                    if (result) {
                        this.next(result.value);
                    } else {
                        throw @lab.errors.not_support;
                    }
                }).then(function(id){

                    lab.find("backend_operation_units",id + "-" + name).pipe(this);

                }).then(function(ou){
                    if (ou) {
                        session.currentOU = ou;
                        this.next(ou,session);
                    } else {
                        throw @lab.errors.not_support;
                    }

                });
            }
            
        },
        @initRegion : function () {
            return @.async(function() {
                    
                lab.sqlite.query("select code from slime_regions").pipe(this);

            }).then(function(code_search_result) {

                var codeMap = {};
                var all_codes = @.keys(regionData["0"]);

                code_search_result.records.forEach(function(record) {
                    codeMap[record.code] = true;
                });

                if (all_codes.filter(function(code) {
                    return !codeMap[code];
                }).length == 0) {

                    this.next();

                } else {

                    @debug("start to init slime regions");

                    var regions = {};
                    var tree = {};

                    all_codes.forEach(function(code) {

                        let slime_region = {
                            id: @.hash.md5(code),
                            name: regionData["0"][code],
                            code: code,
                            path: [],
                            children: []
                        }

                        if (regionData[code]) {
                            slime_region.has_children = true;
                        } else {
                            slime_region.has_children = false;
                        }

                        regions[code] = slime_region;

                    });

                    var country_list = {
                        "1": "中国"
                    }

                    var traverse = function(root_code, root, code, depth, lft_val) {

                        var width = 0;

                        if (code == root_code) {
                            regions[code].depth = 0;
                            regions[code].country = regions[code].name;
                        }

                        var mapping = {
                            "1": "country",
                            "2": "province",
                            "3": "city",
                            "4": "district",
                            "5": "street"
                        };

                        @.keys(root).forEach(function(subcode) {

                            regions[subcode].depth = depth;
                            regions[subcode].parent_id = regions[code].id;
                            regions[subcode].parent_name = regions[code].name;
                            regions[subcode].parent_code = regions[code].code;
                            regions[subcode].country = country_list[root_code];

                            if (mapping[depth - 1]) {
                                regions[subcode][mapping[depth - 1]] = regions[regions[code].parent_code].name;
                            }

                            if (mapping[depth]) {
                                regions[subcode][mapping[depth]] = regions[code].name;
                            }

                            if (mapping[depth + 1]) {
                                regions[subcode][mapping[depth + 1]] = regions[subcode].name;
                            }

                            if (regionData[subcode]) {

                                regions[subcode].lft_val = lft_val + width;
                                width += traverse(root_code, regionData[subcode], subcode, depth + 1, lft_val + width + 1);
                                regions[subcode].rgt_val = lft_val + width + 1;
                                width += 2;

                            } else {
                                regions[subcode].lft_val = lft_val + width;
                                regions[subcode].rgt_val = lft_val + width + 1;
                                width = width + 2;
                            }

                            for (var sdepth = 0; sdepth < depth; ++sdepth) {
                                regions[subcode][mapping[sdepth + 1]] = regions[code][mapping[sdepth + 1]];
                            }



                        });

                        if (code == root_code) {
                            regions[code].lft_val = lft_val;
                            regions[code].rgt_val = lft_val + width;
                        }

                        return width;
                    }

                    var lft_val = 1;

                    @.keys(country_list).forEach(function(country_code) {
                        lft_val += traverse(country_code, regionData[country_code], country_code, 1, lft_val);
                    })

                    @.async.all(@.keys(regions), function(code) {
                        lab.save("slime_regions", regions[code]).pipe(this);
                    }).pipe(this);

                }

            })
        },
        @init: function(options) {
            // 生成微信账号
            return lab.snapshot(function(snapshot) {

                return @.async(function(){

                    snapshot.slime.core.@getSettings().pipe(this);

                }).then(function(settings){

                    this.pool.settings = settings;
                    
                    @.async.all(@.keys(settings),function(name){

                        snapshot.find("slime_system_settings",{
                            "key" : name
                        }).then(function(result){

                            if (result) {
                                this.next();
                            } else {

                                snapshot.create("slime_system_settings",{
                                    key : name,
                                    value : settings[name],
                                    last_update : Date.now()
                                }).then(function () {
                                    snapshot.slime.core.@initRegion().pipe(this);
                                }).pipe(this);

                            }
                        }).pipe(this);

                    }).pipe(this);

                }).all(@.keys(options || {}),function(name){

                    var settings     = this.pool.settings;
                    
                    var predefinedOU = @.merge.advanced({
                        "id"    : {
                            "!valueType" : "string",
                            "!defaultValue" : settings.id + "-" + name
                        },
                        "name"  : {
                            "!valueType" : "string",
                            "!defaultValue" : name
                        },
                        "type"  : {
                            "!valueType" : "string",
                            "!defaultValue" : "brand"
                        },
                        "admin" : {
                            "!valueType" : "object",
                            "!defaultValue" : null,
                            "name" : {
                                "!valueType" : "string"
                            },
                            "account" : {
                                "!valueType" : "string"
                            },
                            "password" : {
                                "!valueType" : "string"
                            }
                        }
                    },options[name]);

                    snapshot.find("backend_operation_units", predefinedOU.id).then(function(existingOU){

                        if (existingOU) {
                            if (existingOU.suffix) {
                                this.next(existingOU);
                            } else {
                                snapshot.update("backend_operation_units",existingOU,{
                                    suffix : name
                                }).pipe(this);
                            }
                            
                        } else {
                            snapshot.create("backend_operation_units",{
                                id     : predefinedOU.id,
                                name   : predefinedOU.name,
                                type   : predefinedOU.type,
                                suffix : name
                            }).pipe(this);
                        }

                    }).then(function(existingOU){

                        this.pool.existingOU = existingOU;
                        if (predefinedOU.admin && predefinedOU.admin.account && predefinedOU.admin.password) {

                            snapshot.backend.user.@getByAccount(predefinedOU.admin.account).then(function(account){
                                if (account ) {
                                    if (account.ouid !== existingOU.id) {
                                        throw @lab.errors.invalid_parameters;    
                                    } else {
                                        this.next(account);
                                    }

                                } else {
                                    snapshot.backend.users.save({
                                        currentOU : existingOU,
                                        currentUser : {
                                            identity : 0,
                                            access : ["admin"]
                                        }
                                    },{
                                        name : predefinedOU.admin.name || predefinedOU.name,
                                        account : predefinedOU.admin.account,
                                        password : predefinedOU.admin.password,
                                        access : ["admin"]
                                    }).pipe(this);
                                }
                            }).pipe(this);
                            
                        } else {
                            this.next();
                        }
                    }).then(function(adminOperator){

                        process.nextTick(() => {

                            @mew.auto("slime.init.ready",{
                                admin : adminOperator,
                                ou    : this.pool.existingOU
                            });

                            @mew.emit("slime.init." + this.pool.existingOU.suffix + ".ready");

                        });

                        this.next();

                    }).pipe(this);
                })
            })
        }
    }
}